class TextDiff {
    // 计算两个文本的差异
    static compare(originalText, modifiedText, options = {}) {
        try {
            const {
                ignoreWhitespace = false,
                ignoreCase = false,
                contextLines = 3,
                splitBy = 'lines', // 'lines', 'words', 'chars'
                showLineNumbers = true
            } = options;

            if (typeof originalText !== 'string' || typeof modifiedText !== 'string') {
                return { success: false, error: '请提供有效的文本内容进行对比' };
            }

            // 预处理文本
            let processedOriginal = originalText;
            let processedModified = modifiedText;

            if (ignoreCase) {
                processedOriginal = processedOriginal.toLowerCase();
                processedModified = processedModified.toLowerCase();
            }

            if (ignoreWhitespace) {
                processedOriginal = processedOriginal.replace(/\s+/g, ' ').trim();
                processedModified = processedModified.replace(/\s+/g, ' ').trim();
            }

            // 分割文本
            let originalParts, modifiedParts;
            switch (splitBy) {
                case 'words':
                    originalParts = this.splitIntoWords(processedOriginal);
                    modifiedParts = this.splitIntoWords(processedModified);
                    break;
                case 'chars':
                    originalParts = processedOriginal.split('');
                    modifiedParts = processedModified.split('');
                    break;
                case 'lines':
                default:
                    originalParts = processedOriginal.split('\n');
                    modifiedParts = processedModified.split('\n');
                    break;
            }

            // 计算差异
            const diffResult = this.computeDiff(originalParts, modifiedParts);
            
            // 生成统一diff格式
            const unifiedDiff = this.generateUnifiedDiff(
                originalText.split('\n'), 
                modifiedText.split('\n'), 
                diffResult, 
                contextLines
            );

            // 生成统一差异HTML视图
            const unifiedHtml = this.generateUnifiedHtml(
                originalText.split('\n'),
                modifiedText.split('\n'),
                diffResult,
                showLineNumbers
            );

            // 统计信息
            const stats = this.calculateStats(diffResult, originalParts, modifiedParts);

            return {
                success: true,
                data: {
                    diff: diffResult,
                    unifiedDiff,
                    unifiedHtml,
                    stats,
                    options
                }
            };

        } catch (error) {
            return { success: false, error: `文本对比失败: ${error.message}` };
        }
    }

    // 使用简化的LCS算法计算差异
    static computeDiff(original, modified) {
        const n = original.length;
        const m = modified.length;
        
        // 创建LCS表
        const lcs = Array(n + 1).fill().map(() => Array(m + 1).fill(0));
        
        // 填充LCS表
        for (let i = 1; i <= n; i++) {
            for (let j = 1; j <= m; j++) {
                if (original[i - 1] === modified[j - 1]) {
                    lcs[i][j] = lcs[i - 1][j - 1] + 1;
                } else {
                    lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]);
                }
            }
        }
        
        // 回溯构建差异序列
        const diff = [];
        let i = n, j = m;
        
        while (i > 0 || j > 0) {
            if (i > 0 && j > 0 && original[i - 1] === modified[j - 1]) {
                // 相同的元素
                diff.unshift({
                    type: 'equal',
                    original: original[i - 1],
                    modified: modified[j - 1],
                    originalIndex: i - 1,
                    modifiedIndex: j - 1
                });
                i--;
                j--;
            } else if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {
                // 插入操作
                diff.unshift({
                    type: 'insert',
                    original: null,
                    modified: modified[j - 1],
                    originalIndex: -1,
                    modifiedIndex: j - 1
                });
                j--;
            } else if (i > 0) {
                // 删除操作
                diff.unshift({
                    type: 'delete',
                    original: original[i - 1],
                    modified: null,
                    originalIndex: i - 1,
                    modifiedIndex: -1
                });
                i--;
            }
        }
        
        return diff;
    }


    // 生成统一diff格式
    static generateUnifiedDiff(originalLines, modifiedLines, diffResult, contextLines = 3) {
        let unifiedDiff = '';
        let originalLineCount = 0;
        let modifiedLineCount = 0;
        
        // 计算行数
        for (const change of diffResult) {
            if (change.type === 'equal' || change.type === 'delete') {
                originalLineCount++;
            }
            if (change.type === 'equal' || change.type === 'insert') {
                modifiedLineCount++;
            }
        }

        unifiedDiff += `@@ -1,${originalLineCount} +1,${modifiedLineCount} @@\n`;

        for (const change of diffResult) {
            switch (change.type) {
                case 'equal':
                    unifiedDiff += ` ${change.original || ''}\n`;
                    break;
                case 'delete':
                    unifiedDiff += `-${change.original || ''}\n`;
                    break;
                case 'insert':
                    unifiedDiff += `+${change.modified || ''}\n`;
                    break;
            }
        }

        return unifiedDiff;
    }

    // 生成统一差异HTML视图
    static generateUnifiedHtml(originalLines, modifiedLines, diffResult, showLineNumbers = true) {
        let html = '<div class="diff-container bg-gray-50 rounded-lg border border-gray-200 overflow-hidden">';
        
        let originalLineNum = 1;
        let modifiedLineNum = 1;

        for (const change of diffResult) {
            switch (change.type) {
                case 'equal':
                    html += this.generateUnifiedDiffLine('equal', change.original, originalLineNum, modifiedLineNum, showLineNumbers);
                    originalLineNum++;
                    modifiedLineNum++;
                    break;
                case 'delete':
                    html += this.generateUnifiedDiffLine('delete', change.original, originalLineNum, null, showLineNumbers);
                    originalLineNum++;
                    break;
                case 'insert':
                    html += this.generateUnifiedDiffLine('insert', change.modified, null, modifiedLineNum, showLineNumbers);
                    modifiedLineNum++;
                    break;
            }
        }

        html += '</div>';
        return html;
    }

    // 生成统一差异视图的单行HTML
    static generateUnifiedDiffLine(type, content, originalLineNum, modifiedLineNum, showLineNumbers) {
        let classes = 'diff-line px-4 py-2 text-sm font-mono transition-colors duration-150';
        let bgClass = '';
        let prefix = '';
        let textClass = '';
        let borderClass = '';
        let prefixBg = '';

        switch (type) {
            case 'equal':
                bgClass = 'bg-white hover:bg-gray-50';
                prefix = ' ';
                textClass = 'text-gray-700';
                prefixBg = 'bg-gray-100 text-gray-500';
                break;
            case 'delete':
                bgClass = 'bg-red-50 hover:bg-red-100';
                prefix = '-';
                textClass = 'text-red-700';
                borderClass = 'border-l-4 border-red-300';
                prefixBg = 'bg-red-200 text-red-600';
                break;
            case 'insert':
                bgClass = 'bg-green-50 hover:bg-green-100';
                prefix = '+';
                textClass = 'text-green-700';
                borderClass = 'border-l-4 border-green-300';
                prefixBg = 'bg-green-200 text-green-600';
                break;
        }

        let lineNumHtml = '';
        if (showLineNumbers) {
            const origNum = originalLineNum ? originalLineNum.toString().padStart(3, ' ') : '   ';
            const modNum = modifiedLineNum ? modifiedLineNum.toString().padStart(3, ' ') : '   ';
            lineNumHtml = `<div class="flex-shrink-0 text-xs text-gray-400 bg-gray-100 px-3 py-1 mr-4 rounded-sm select-none">
                <span class="inline-block w-6 text-right">${origNum}</span>
                <span class="mx-1 text-gray-300">|</span>
                <span class="inline-block w-6 text-left">${modNum}</span>
            </div>`;
        }
        
        return `<div class="${classes} ${bgClass} ${textClass} ${borderClass} border-b border-gray-100 last:border-b-0">
            <div class="flex items-start">
                ${lineNumHtml}
                <div class="flex-shrink-0 w-6 h-6 rounded-sm ${prefixBg} flex items-center justify-center font-bold text-xs mr-3">${prefix}</div>
                <div class="flex-1 leading-6 whitespace-pre-wrap break-words min-h-[1.5rem]">${this.escapeHtml(content || '')}</div>
            </div>
        </div>`;
    }

    // 将差异分组为hunks
    static groupIntoHunks(diffResult, contextLines) {
        const hunks = [];
        let currentHunk = null;

        for (let i = 0; i < diffResult.length; i++) {
            const change = diffResult[i];
            
            if (change.type !== 'equal' || this.isNearChange(diffResult, i, contextLines)) {
                if (!currentHunk) {
                    currentHunk = {
                        originalStart: Math.max(0, change.originalIndex - contextLines),
                        modifiedStart: Math.max(0, change.modifiedIndex - contextLines),
                        originalEnd: change.originalIndex,
                        modifiedEnd: change.modifiedIndex,
                        changes: []
                    };
                }
                
                currentHunk.changes.push(change);
                if (change.originalIndex >= 0) currentHunk.originalEnd = change.originalIndex;
                if (change.modifiedIndex >= 0) currentHunk.modifiedEnd = change.modifiedIndex;
            } else if (currentHunk) {
                hunks.push(currentHunk);
                currentHunk = null;
            }
        }

        if (currentHunk) {
            hunks.push(currentHunk);
        }

        return hunks;
    }

    // 检查是否接近变更
    static isNearChange(diffResult, index, contextLines) {
        for (let i = Math.max(0, index - contextLines); i < Math.min(diffResult.length, index + contextLines + 1); i++) {
            if (diffResult[i].type !== 'equal') {
                return true;
            }
        }
        return false;
    }

    // 分割为单词
    static splitIntoWords(text) {
        return text.match(/\S+|\s+/g) || [];
    }

    // 计算统计信息
    static calculateStats(diffResult, originalParts, modifiedParts) {
        let insertions = 0;
        let deletions = 0;
        let modifications = 0;
        let unchanged = 0;

        for (const change of diffResult) {
            switch (change.type) {
                case 'insert':
                    insertions++;
                    break;
                case 'delete':
                    deletions++;
                    break;
                case 'equal':
                    unchanged++;
                    break;
            }
        }

        // 估算修改行数（连续的删除和插入视为修改）
        modifications = Math.min(insertions, deletions);
        insertions = Math.max(0, insertions - modifications);
        deletions = Math.max(0, deletions - modifications);

        const totalChanges = insertions + deletions + modifications;
        const similarity = originalParts.length > 0 ? 
            ((originalParts.length - totalChanges) / originalParts.length * 100).toFixed(1) : 
            100;

        return {
            originalLength: originalParts.length,
            modifiedLength: modifiedParts.length,
            insertions,
            deletions,
            modifications,
            unchanged,
            totalChanges,
            similarity: parseFloat(similarity)
        };
    }

    // HTML转义
    static escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // 导出差异结果
    static exportDiff(diffData, format = 'unified') {
        try {
            switch (format) {
                case 'unified':
                    return {
                        success: true,
                        data: {
                            content: diffData.unifiedDiff,
                            filename: `diff_${new Date().getTime()}.patch`,
                            mimeType: 'text/plain'
                        }
                    };
                case 'html':
                    const htmlContent = `
<!DOCTYPE html>
<html>
<head>
    <title>文本差异对比</title>
    <meta charset="UTF-8">
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50">
    <div class="container mx-auto p-6">
        <h1 class="text-3xl font-bold mb-6 text-gray-800">文本差异对比结果</h1>
        <div class="bg-white rounded-lg shadow-lg">
            ${diffData.unifiedHtml}
        </div>
    </div>
</body>
</html>`;
                    return {
                        success: true,
                        data: {
                            content: htmlContent,
                            filename: `diff_${new Date().getTime()}.html`,
                            mimeType: 'text/html'
                        }
                    };
                default:
                    return { success: false, error: '不支持的导出格式' };
            }
        } catch (error) {
            return { success: false, error: `导出失败: ${error.message}` };
        }
    }

    // 文件内容对比
    static compareFiles(file1Content, file2Content, file1Name, file2Name, options = {}) {
        try {
            const result = this.compare(file1Content, file2Content, options);
            
            if (result.success) {
                result.data.fileInfo = {
                    originalName: file1Name || '文件1',
                    modifiedName: file2Name || '文件2',
                    originalSize: file1Content.length,
                    modifiedSize: file2Content.length
                };
            }
            
            return result;
        } catch (error) {
            return { success: false, error: `文件对比失败: ${error.message}` };
        }
    }
}